home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / tvision / dpmi / dpmirun / loadprog.cpp < prev   
Encoding:
C/C++ Source or Header  |  1994-05-29  |  42.1 KB  |  1,459 lines

  1. //=====================================================================
  2. //
  3. //  loadprog.cpp
  4. //
  5. //  Actually load new executable images, and Borland debug symbol
  6. //  information if it exists.
  7. //
  8. //  Copyright (c) 1994, Kevin Morgan, All rights reserved.
  9. //
  10. //=====================================================================
  11. //
  12. //#define DEBUG
  13. #ifdef DEBUG
  14. //#define DEBUGNAMES
  15. //#define DEBUGSYMBOLS
  16. #endif
  17.  
  18. #define errprint printf
  19.  
  20. #include "dpmirun.h"
  21.  
  22. #include "exedef.h"     // defines structure of New Executable .EXE image
  23.  
  24. class near DebugInfo;
  25.  
  26. //=====================================================================
  27. //
  28. // RealModuleLoader
  29. // this class implements the loading process that is abstracted
  30. // in ModuleLoader.
  31. //
  32. //=====================================================================
  33. class near RealModuleLoader : public ModuleLoader
  34. {
  35.     friend DebugInfo;
  36.     protected:
  37.         SegmentTable *segTable;
  38.  
  39.         Selector *selectors;
  40.  
  41.         int loadErrorCount;
  42.  
  43.         DWORD headeroffset, lastbyte;
  44.  
  45.         long endOfImage;    // positions after relocations for last segment
  46.  
  47.         HEADER header;
  48.  
  49.         NEHEADER newHeader;
  50.  
  51.         DebugInfo *debugInfo;
  52.  
  53.         char fname[80];
  54.  
  55.         int inf;
  56.  
  57.  
  58.     public:
  59.         RealModuleLoader() : 
  60.             segTable(0),
  61.             selectors(0),
  62.             loadErrorCount(0),
  63.             debugInfo(0),
  64.             endOfImage(0),
  65.             ModuleLoader() { }
  66.         virtual void _far *entryPoint();
  67.         virtual char *describeFaultPc(WORD& nearCs, WORD cs, WORD ip);
  68.         virtual void far *getStack(unsigned);
  69.         virtual void loadExecutable(char *);
  70.         virtual void adjustSelectors();
  71.         virtual int loadErrors() { return loadErrorCount; }
  72.  
  73.         // implementation specific methods
  74.         Selector *allocSelectors(int);
  75.         SegmentTable *allocSegTables(int);
  76.         int getLogicalSelector(WORD cs, WORD& lcs);
  77.         void read_segment_table(int inf, int nsegs, SegmentTable *tablePtr);
  78.         int readSegmentData(int nsegs, SegmentTable *tablePtr, Selector *selectors);
  79.         int readRelocations(int segNr, SegmentTable *st, Selector *selectors);
  80. };
  81.  
  82. FILE *loadlogf = 0;
  83.  
  84.  
  85. //=====================================================================
  86. //
  87. //  dprintf -- print diagnostic info to our diag file.
  88. //
  89. //=====================================================================
  90. #pragma argsused
  91. void dprintf(char *fmt,...)
  92. {
  93. #ifdef DEBUG
  94.     va_list argptr;
  95.     char vbuf[160];
  96.     va_start(argptr, fmt);
  97.     vsprintf(vbuf, fmt,  argptr);
  98.     va_end(argptr);
  99.     if (!loadlogf) {
  100.         loadlogf = fopen("diag.tmp","w+t");
  101.     }
  102.     if (loadlogf) {
  103.         fprintf(loadlogf, "%s", vbuf);
  104.         fflush(loadlogf);
  105.     }
  106. #endif
  107. }
  108.  
  109. //=====================================================================
  110. //
  111. //  kprintf -- print diagnostic info to our diag file.
  112. //
  113. //=====================================================================
  114. #pragma argsused
  115. void kprintf(char *fmt,...)
  116. {
  117.     va_list argptr;
  118.     char vbuf[160];
  119.     va_start(argptr, fmt);
  120.     vsprintf(vbuf, fmt,  argptr);
  121.     va_end(argptr);
  122.     if (!loadlogf) {
  123.         loadlogf = fopen("diag.tmp","w+t");
  124.     }
  125.     if (loadlogf) {
  126.         fprintf(loadlogf, "%s", vbuf);
  127.         fflush(loadlogf);
  128.     }
  129.     printf("%s", vbuf);
  130.     fflush(stdout);
  131. }
  132.  
  133. //=====================================================================
  134. //
  135. //  lread -- read from a file into a far memory region
  136. //
  137. //=====================================================================
  138. DWORD lread(int inf, char _far *p, DWORD len)
  139. {
  140.     DWORD tbytes = 0;
  141.     DWORD bytes;
  142.     char *buf = new char[4096];
  143.     while (len>0) {
  144.         DWORD sz = len;
  145.         if (len>4096) sz = 4096;
  146.         bytes = read(inf, buf, sz);
  147.         if (bytes==0xffff) { tbytes=bytes; break; }
  148.         _fmemcpy(p, buf, sz);
  149.         p += sz;
  150.         tbytes+=bytes;
  151.         len -= bytes;
  152.     }
  153.     delete [] buf;
  154.     return tbytes;
  155. }
  156.  
  157. #ifdef DIAGS
  158. //=====================================================================
  159. //
  160. //  dump_dpmi_information
  161. //
  162. //  interrogate our dpmi server and print what we find.
  163. //
  164. //=====================================================================
  165. int dump_dpmi_information(int , char *[])
  166. {
  167.     clrscr();
  168.     gotoxy(1,1);
  169.     {
  170.         dprintf("get dpmi version\n");
  171.         int maj,min,flags;
  172.         int res = Dpmi.getVersion(maj,min,flags);
  173.         if (res!=DPMI_OK) 
  174.             dprintf("no DPMI 0.9 capabilities\n");
  175.         else {
  176.             dprintf("DPMI ver %d.%d\n", maj,min);
  177.             dprintf("running on 32-bit DPMI: %s\n", flags&1?"yes":"no");
  178.             dprintf("interrupts in RM      : %s\n", flags&2?"yes":"no");
  179.             dprintf("virtual memory support: %s\n", flags&4?"yes":"no");
  180.         }
  181.     }
  182.  
  183.  
  184.     {
  185.         static char buf[128];
  186.         char _far *bufp = buf;
  187.         int flags;
  188.         int res = Dpmi.getCapabilities(bufp, flags);
  189.         if (res!=DPMI_OK) 
  190.             dprintf("no DPMI 1.0 capabilities\n");
  191.         else {
  192.             dprintf("DPMI ver %d.%d %s\n", buf[0], buf[1], buf+2);
  193.             dprintf("page accessed         : %s\n", flags&1?"yes":"no");
  194.             dprintf("exceptions restartable: %s\n", flags&2?"yes":"no");
  195.             dprintf("device mapping support: %s\n", flags&4?"yes":"no");
  196.             dprintf("conventional mapping  : %s\n", flags&8?"yes":"no");
  197.             dprintf("demand zero-fill      : %s\n", flags&16?"yes":"no");
  198.             dprintf("write protect client  : %s\n", flags&32?"yes":"no");
  199.             dprintf("write protect host    : %s\n", flags&64?"yes":"no");
  200.         }
  201.     }
  202.  
  203.     return 0;
  204. }
  205. #endif
  206.  
  207. //=====================================================================
  208. //
  209. //  dumpItem
  210. //
  211. //  diagnostic hex dump of areas read
  212. //
  213. //=====================================================================
  214. void dumpItem(char *title, void *ptr, size_t sz)
  215. {
  216.     unsigned *p = (unsigned *)ptr;
  217.     dprintf("%s\n", title);
  218.     int i;
  219.     for (i=0;i<sz/2;i++) {
  220.         if (i%8==0) dprintf("%04x: ",i);
  221.         dprintf("%04x ", *p++);
  222.         if (i%8==7) dprintf("\n");
  223.     }
  224.     dprintf("\n");
  225. }
  226.  
  227. //=====================================================================
  228. //
  229. //  FarMemoryPool
  230. //
  231. //  Manage a memory pool allocated with DPMI
  232. //
  233. //=====================================================================
  234. class FarMemoryPool
  235. {
  236.     protected:
  237.         Selector poolSeg;
  238.         unsigned long poolSize;
  239.         unsigned long poolCnt;
  240.         unsigned long allocationUnit;
  241.     public:
  242.         FarMemoryPool(unsigned long allocSz=32768) :
  243.             poolSeg(0), poolSize(0),
  244.             poolCnt(0), allocationUnit(allocSz) { }
  245.         void far *getMemory(unsigned long sz);
  246. };
  247.  
  248.  
  249. void far *FarMemoryPool::getMemory(unsigned long sz)
  250. {
  251.     // DWORD alignment
  252.     sz += 3;
  253.     sz -= (sz&3);
  254.  
  255.     if (poolSeg==0 || poolCnt+sz>poolSize) { // need to allocate
  256.         poolSeg = 0;
  257.         poolCnt = 0;
  258.         if (Dpmi.getMappedMemory(allocationUnit, poolSeg, AccessRightsData)!=DPMI_OK)
  259.             return 0;
  260.         poolSize = allocationUnit;
  261.     }
  262.     if (poolSeg==0 || poolCnt+sz>poolSize)  // Oops!
  263.         return 0;
  264.     void far *p = MK_FP(poolSeg, poolCnt);
  265.     poolCnt += sz;
  266.     return p;
  267. }
  268.  
  269. FarMemoryPool pool;
  270.  
  271. //=====================================================================
  272. //
  273. //  SparseObjectTable
  274. //
  275. //  A table of objects stored in protected mode memory
  276. //
  277. //  We allow a number of objects limited only by available memory,
  278. //  despite the protected mode 64K segment limit.
  279. //
  280. //=====================================================================
  281. typedef void SparseObject;
  282.  
  283. typedef SparseObject far *SparseObjectPtr;
  284.  
  285. class SparseObjectTable 
  286. {
  287.     protected:
  288.  
  289.         long objectCount;   // number of objects in the table
  290.  
  291.         SparseObjectPtr far * objects;
  292.  
  293.         SparseObjectPtr far * newObjectTable();
  294.  
  295.     public:
  296.         SparseObjectTable(long aCount=0);
  297.  
  298.         SparseObjectPtr fetch(unsigned long n);
  299.  
  300.         void store(unsigned long, SparseObjectPtr);
  301. };
  302.  
  303. SparseObjectPtr far * SparseObjectTable::newObjectTable()
  304. {
  305.     SparseObjectPtr far *p;
  306.     unsigned nObjects = 256;
  307.     p = (SparseObjectPtr far *) pool.getMemory(nObjects*sizeof(SparseObjectPtr far *));
  308.     if (!p) return 0;
  309.     int i;
  310.     for (i=0;i<nObjects;i++) 
  311.         p[i] = 0;
  312.     return p;
  313. }
  314.  
  315.  
  316. SparseObjectTable::SparseObjectTable(long aCount) : 
  317.         objectCount(aCount),
  318.         objects(0)
  319. {
  320.     if (objectCount==0) {
  321.         objectCount = 1l << 30;
  322.     }
  323. }
  324.  
  325. // returns a pointer to the n'th object
  326. SparseObjectPtr SparseObjectTable::fetch(unsigned long n)
  327. {
  328.     if (n>=objectCount)
  329.         return 0;
  330.     unsigned char a = (n >> 24)&255;
  331.     unsigned char b = (n >> 16)&255;
  332.     unsigned char c = (n >> 8)&255;
  333.     unsigned char d = n & 255;
  334.  
  335.     SparseObjectPtr far * p = objects;
  336.     if (!p) return 0;
  337.     p = (SparseObjectPtr far *) p[a];
  338.     if (!p) return 0;
  339.     p = (SparseObjectPtr far *) p[b];
  340.     if (!p) return 0;
  341.     p = (SparseObjectPtr far *) p[c];
  342.     if (!p) return 0;
  343.     p = (SparseObjectPtr far *) p[d];
  344.     return p;
  345. }
  346.  
  347. void SparseObjectTable::store(unsigned long n, SparseObjectPtr anObject)
  348. {
  349.     if (n>=objectCount)
  350.         return;
  351.     if (!objects)
  352.         objects = newObjectTable();
  353.  
  354.     SparseObjectPtr far * p = objects;
  355.     unsigned char a = (n >> 24)&255;
  356.     unsigned char b = (n >> 16)&255;
  357.     unsigned char c = (n >> 8)&255;
  358.     unsigned char d = n & 255;
  359.  
  360.     SparseObjectPtr far * q;
  361.     q = (SparseObjectPtr far *) p[a];
  362.     if (!q) p[a]=q=newObjectTable();
  363.     p = q;
  364.  
  365.     q = (SparseObjectPtr far *) p[b];
  366.     if (!q) p[b]=q=newObjectTable();
  367.     p = q;
  368.  
  369.     q = (SparseObjectPtr far *) p[c];
  370.     if (!q) p[c]=q=newObjectTable();
  371.     p = q;
  372.  
  373.     p[d] = anObject;
  374. }
  375.  
  376.  
  377. //=====================================================================
  378. //
  379. //  SpellingTable
  380. //
  381. //  A class to manage the debug name information stored in an executable
  382. //
  383. //=====================================================================
  384. class SpellingTable : public SparseObjectTable
  385. {
  386.     public:
  387.         SpellingTable(long aCount=0) :
  388.             SparseObjectTable(aCount) { }
  389.             
  390.  
  391.         char far *operator[](unsigned long n)
  392.             { return (char far *) fetch(n); }
  393.  
  394.         void store(unsigned long n, char far *anObject) {
  395.             SparseObjectTable::store(n, anObject);
  396.         }
  397. };
  398.  
  399. //=====================================================================
  400. //
  401. //  SymbolTable
  402. //
  403. //  A class to manage the debug symbol information stored in an executable
  404. //
  405. //=====================================================================
  406. class SymbolTable : public SparseObjectTable
  407. {
  408.     public:
  409.         SymbolTable(long aCount=0) :
  410.             SparseObjectTable(aCount) { }
  411.             
  412.  
  413.         DebugSymbol far *operator[](unsigned long n)
  414.             { return (DebugSymbol far *) fetch(n); }
  415.  
  416.         void store(unsigned long n, DebugSymbol far *anObject) {
  417.             SparseObjectTable::store(n,anObject);
  418.         }
  419. };
  420.  
  421. //=====================================================================
  422. //
  423. //  LineNumberTable
  424. //
  425. //  A class to manage the debug line numbers stored in an executable
  426. //
  427. //=====================================================================
  428. class LineNumberTable : public SparseObjectTable
  429. {
  430.     public:
  431.         LineNumberTable(long aCount=0) :
  432.             SparseObjectTable(aCount) { }
  433.             
  434.  
  435.         DebugLineNumber far *operator[](unsigned long n)
  436.             { return (DebugLineNumber far *) fetch(n); }
  437.  
  438.         void store(unsigned long n, DebugLineNumber far *anObject) {
  439.             SparseObjectTable::store(n,anObject);
  440.         }
  441. };
  442.  
  443. //=====================================================================
  444. //
  445. //  DebugInfo
  446. //
  447. //  A class to manage the debug information stored in an executable
  448. //
  449. //=====================================================================
  450. class near DebugInfo
  451. {
  452.     protected:
  453.         RealModuleLoader *theModule;
  454.         SpellingTable nameTable;
  455.         SymbolTable symbols;
  456.         LineNumberTable lineNumbers;
  457.  
  458.         unsigned codeviewHeader[8];
  459.  
  460.         DebugModule *modules;
  461.         DebugSourceFile *sourceFiles;
  462.         DebugScope   *scopeRecords;
  463.         DebugSegment *segments;
  464.         DebugCorrelation *correlations;
  465.  
  466.         DebugHeader debugHeader;
  467.  
  468.         DebugExtHeader debugExtHeader;
  469.  
  470.     public:
  471.         DebugInfo(RealModuleLoader *aModule) :
  472.             theModule(aModule),
  473.             nameTable(0),
  474.             symbols(0),
  475.             modules(0),
  476.             sourceFiles(0),
  477.             lineNumbers(0),
  478.             scopeRecords(0),
  479.             correlations(0),
  480.             segments(0) { }
  481.         int readDebugInfo();
  482.         void readNames();
  483.         void readSymbols();
  484.         void readLineNumbers();
  485.         char *symbolName(int i);
  486.         char *moduleName(int i) { return symbolName( modules[i-1].moduleName ); }
  487.         char *sourceName(int i) { return symbolName( sourceFiles[i-1].sourceFileName ); }
  488.         char *describeFaultPc(WORD,WORD);
  489.         alignmentShift() { return theModule->newHeader.fileAlignmentShift; }
  490.         void loadError(char *msg) { theModule->loadErrorCount++; dprintf(msg); }
  491.         void searchCorrelations(char *buf, DebugSegment *p, WORD ip);
  492.  
  493. };
  494.  
  495.  
  496.  
  497. char *DebugInfo::symbolName(int i) {
  498.     static char buf[80];
  499.     char *q = buf;
  500.     char far *p = nameTable[i-1];
  501.     if (!p) return "Unknown";
  502.     int j;
  503.     for (j=0; (j<79) && (*p);j++)
  504.         *q++ = *p++;
  505.     *q++ = 0;
  506.     return buf;
  507. }
  508.  
  509. void DebugInfo::searchCorrelations(char *lbuf, DebugSegment *p, WORD ip)
  510. {
  511. //dprintf("searchCorrelations(%04x)\n", ip);
  512.     *lbuf = '\0';
  513.     if (correlations) {
  514.         DebugLineNumber far *aLine=0;
  515.         DebugCorrelation *aCore = 0;
  516.         int i;
  517.         for (i=0;i<p->correlationCount;i++) {
  518.             DebugCorrelation *correlation = 
  519.                 correlations+p->correlationIndex+i-1;
  520.             int ln;
  521.             DebugSegment *seg = segments+correlation->segmentIndex-1;
  522.             unsigned rip = ip; // - seg->codeOffset;
  523. //dprintf("relative offset=%04x of segment %d of correlation %d\n",
  524. //            rip, correlation->segmentIndex, p->correlationIndex+i);
  525.             for (ln=0;ln<correlation->linesCount;ln++) {
  526.                 DebugLineNumber far *line
  527.                     = lineNumbers[correlation->linesIndex+ln-1];
  528. //dprintf("line %d = %04x\n", line->lineNumberValue, line->lineNumberOffset);
  529.                 if (!aLine) {
  530.                     aCore = correlation;
  531.                     aLine = line;
  532.                 }
  533.                 else if (line->lineNumberOffset < rip &&
  534.                          line->lineNumberOffset > aLine->lineNumberOffset) {
  535.                     aCore = correlation;
  536.                     aLine = line;
  537.                 }
  538.             }
  539.         }
  540.         if (aLine)
  541.             sprintf(lbuf, "line %d of %s",
  542.                 aLine->lineNumberValue, sourceName(aCore->fileIndex) );
  543.     }
  544. }
  545.  
  546. //=====================================================================
  547. //
  548. //  DebugInfo::descripeFaultPc
  549. //
  550. //  given a logical CS:IP, describe in symbolic terms where
  551. //  that is.
  552. //
  553. //  This procedure does not take full advantage of the information
  554. //  available in the debug symbol table.
  555. //
  556. //  It just looks for the nearest symbol in that segment.
  557. //
  558. //=====================================================================
  559. char *DebugInfo::describeFaultPc(WORD lcs,WORD ip)
  560. {
  561.     static char buf[80];
  562.     static char mbuf[40];
  563.     buf[0] = '\0';
  564.     int i;
  565.     if (segments) {
  566.         for (i=0;i<debugHeader.segmentCount;i++) {
  567.             DebugSegment *p = segments+i;
  568.             if ( p->codeSegment == lcs &&
  569.                     ip >= p->codeOffset &&
  570.                     ip <  p->codeOffset+p->codeLength ) {
  571.  
  572.                 searchCorrelations(buf, p, ip);
  573.                 if (!buf[0]) {
  574.                     sprintf(buf,"%s+%04xh",
  575.                             moduleName(p->modIndex),
  576.                             ip-p->codeOffset );
  577.                 }
  578.                 // here we should search the correlations
  579.                 // starting at correlationIndex for correlationCount
  580.                 goto doSymbol;
  581.             }
  582.         }
  583.     }
  584. //    strcat(buf, "in Unknown module");
  585. doSymbol:
  586.     DebugSymbol far *q = 0;
  587.     for (i=0;i<debugHeader.symbolsCount;i++) {
  588.         DebugSymbol far *p = symbols[i];
  589.         if (lcs==p->symbolSegment&&p->symbolOffset<=ip)
  590.             if (!q)
  591.                 q = p;
  592.             else if (p->symbolOffset>q->symbolOffset)
  593.                 q = p;
  594.     }
  595.     if (q) {
  596.         sprintf(mbuf, "%s+%04x",
  597.             symbolName(q->symbolName),
  598. //            q->symbolSegment,
  599. //            q->symbolOffset,
  600.             ip-q->symbolOffset);
  601.         if (buf[0]) strcat(buf, " or ");
  602.         strcat(buf, mbuf);
  603.         goto done;
  604.     }
  605.     sprintf(buf, "Unknown func (%04x:%04x)",
  606.             lcs, ip);
  607. done:
  608. //  dprintf("describeFaultPc: %s\n", buf);
  609.     return buf;
  610. }
  611.  
  612. //=====================================================================
  613. //
  614. //  readNames
  615. //
  616. //  read name entries from the image
  617. //
  618. //=====================================================================
  619. void DebugInfo::readNames()
  620. {
  621.     int inf = theModule->inf;
  622.     const NameBufSize = 4096;
  623.     char *buf = new char[NameBufSize];
  624.     char name[80];
  625.     unsigned long pos = 0;
  626.     unsigned long namenr = 0;
  627.     int n = 0;
  628.     while (pos < debugHeader.names) {
  629.         unsigned long nbytes = debugHeader.names-pos;
  630.         if (nbytes>NameBufSize) nbytes = NameBufSize;
  631.         int sz=read(inf, buf, nbytes);
  632.         if (sz!=nbytes) {
  633.             loadError("readNames read error\n");
  634.             return;
  635.         }
  636.         int i;
  637.         for (i=0;i<nbytes;i++) {
  638.             name[n] = buf[i];
  639.             if (n<79) n++;
  640.             if (buf[i]==0) {
  641.                 char far *p = (char far *) pool.getMemory(n);
  642.                 _fstrcpy(p, name);
  643.                 n = 0;
  644.                 nameTable.store(namenr,p);
  645.                 namenr++;
  646.             }
  647.         }
  648.         pos += nbytes;
  649.     }
  650.     delete [] buf;
  651. #ifdef DEBUGNAMES
  652.     long i;
  653.     for (i=0;i<namenr;i++) {
  654.         char far *p = nameTable[i];
  655.         _fstrcpy(name,p);
  656. dprintf("%04x:%04x Name Entry %ld: %s\n",
  657.         FP_SEG(p), FP_OFF(p),
  658.         i, 
  659.         name);
  660.     }
  661. #endif
  662. }
  663.  
  664. //=====================================================================
  665. //
  666. //  readSymbols
  667. //
  668. //  read symbol entries from the image
  669. //
  670. //=====================================================================
  671. void DebugInfo::readSymbols()
  672. {
  673.     // read symbols
  674.     dprintf("Symbol Table: %d symbols\n", debugHeader.symbolsCount);
  675.  
  676.     int inf = theModule->inf;
  677.  
  678.     DebugSymbol *aSymbol = new DebugSymbol[32];
  679.     unsigned i=0;
  680.     while(i<debugHeader.symbolsCount) {
  681.         int k = debugHeader.symbolsCount-i;
  682.         if (k>32) k = 32;
  683.         int sz=read(inf, (void *) aSymbol, k*sizeof(DebugSymbol) );
  684.         if (sz!=k*sizeof(DebugSymbol)) {
  685.             loadError("readSymbols cannot read symbols\n");
  686.             return;
  687.         }
  688.         DebugSymbol far *p = (DebugSymbol far *) pool.getMemory(k*sizeof(DebugSymbol));
  689.         _fmemcpy(p, aSymbol, k*sizeof(DebugSymbol));
  690.         int j;
  691.         for (j=0;j<k;j++)
  692.             symbols.store(i+j,p+j);
  693.  
  694.         i += k;
  695.  
  696.     }
  697.  
  698. #ifdef DEBUGSYMBOLS
  699.     for (i=0;i<debugHeader.symbolsCount;i++) {
  700.         DebugSymbol far *p = symbols[i];
  701.         dprintf("%04x:%04x Symbol %3d: %04x:%04x %s\n",
  702.             FP_SEG(p), FP_OFF(p),
  703.             i,
  704.             p->symbolSegment,
  705.             p->symbolOffset,
  706.             symbolName(p->symbolName));
  707.     }
  708. #endif
  709.  
  710.     delete [] aSymbol;
  711. }
  712.  
  713. //=====================================================================
  714. //
  715. //  readLineNumbers
  716. //
  717. //  read line number entries from the image
  718. //
  719. //=====================================================================
  720. void DebugInfo::readLineNumbers()
  721. {
  722.     // read line numbers
  723.     unsigned i = 0;
  724.     DebugLineNumber * aLine = new DebugLineNumber[128];
  725.  
  726.     int inf = theModule->inf;
  727.  
  728.     while (i<debugHeader.linesCount) {
  729.         int k = debugHeader.linesCount-i;
  730.         if (k>128) k = 128;
  731.         int sz=read(inf, (void *) aLine, k*sizeof(DebugLineNumber) );
  732.         if (sz!=k*sizeof(DebugLineNumber)) {
  733.             loadError("readLineNumbers cannot read LineNumbers\n");
  734.             return;
  735.         }
  736.         DebugLineNumber far *p = (DebugLineNumber far *) pool.getMemory(k*sizeof(DebugLineNumber));
  737.         _fmemcpy(p, aLine, k*sizeof(DebugLineNumber));
  738.         int j;
  739.         for (j=0;j<k;j++)
  740.             lineNumbers.store(i+j,p+j);
  741.  
  742.         i += k;
  743.  
  744.     }
  745.  
  746.     delete [] aLine;
  747. }
  748.  
  749. //=====================================================================
  750. //
  751. //  readDebugInfo
  752. //
  753. //  read the Borland Debug information table from the image
  754. //
  755. //=====================================================================
  756. int DebugInfo::readDebugInfo()
  757. {
  758.     dprintf("readDebugInfo\n");
  759.     long mask = 1l << alignmentShift();
  760.     long pos = theModule->endOfImage;
  761.     int tries= 0;
  762.     pos += mask-1;
  763.     pos -= pos%mask;
  764.  
  765.     int inf = theModule->inf;
  766.     {
  767.         lseek(inf, pos, SEEK_SET);
  768.         read(inf, (void *)&codeviewHeader, 16);
  769.         dumpItem("CodeViewHeader", &codeviewHeader, sizeof(codeviewHeader));
  770.         pos += sizeof(codeviewHeader);
  771.     }
  772.  
  773. retryLoad:
  774.     lseek(inf, pos, SEEK_SET);
  775.     unsigned sz=read(inf, (void *) &debugHeader, sizeof(DebugHeader) );
  776.     if (sz!=sizeof(DebugHeader)) {
  777.         dprintf("readDebugInfo cannot read header\n");
  778.         return DPMI_OK;
  779.     }
  780.  
  781.     dumpItem("DebugHeader", &debugHeader, sizeof(DebugHeader));
  782.  
  783.     if (debugHeader.magicNumber!=DEBUG_MAGIC) {
  784.         if (tries) {
  785.             dprintf("cannot find debug header\n");
  786.             return DPMI_OK;
  787.         }
  788.         tries++;
  789. #ifndef DEBUGMAGIC
  790.         unsigned *buf = new unsigned[256];
  791.         DWORD npos = 0;
  792.         dprintf("expected magic number at %08lxx\n", pos);
  793.         lseek(inf, npos, SEEK_SET);
  794.         for (;;) {
  795.             if (read(inf, (char *)buf, 512)!=512) break;
  796.             int i;
  797.             for (i=0;i<256;i++)
  798.                 if (buf[i]==DEBUG_MAGIC) {
  799.                     pos = npos+2*i;
  800.                     dprintf("magic number found at %08lxx\n", npos+2*i);
  801.                 }
  802.             npos += 512;
  803.         }
  804.         delete [] buf;
  805.         goto retryLoad;
  806. #endif
  807.  
  808.     }
  809.  
  810.     unsigned bytes = sizeof(DebugExtHeader);
  811.     if (bytes>debugHeader.extensionSize)
  812.         bytes = debugHeader.extensionSize;
  813.  
  814.     dprintf("header extensionSize = %d\n", debugHeader.extensionSize);
  815.  
  816.     sz=read(inf, &debugExtHeader, bytes );
  817.     if (sz!=bytes) {
  818.         loadError("readDebugInfo cannot read header extention\n");
  819.         return DPMI_ERR;
  820.     }
  821.  
  822.     dumpItem("DebugExtHeader", &debugExtHeader, sizeof(DebugExtHeader));
  823.  
  824.     long symbolBase = pos + sizeof(DebugHeader)+debugHeader.extensionSize;
  825.  
  826.     lseek(inf, symbolBase+debugExtHeader.namePoolOffset, SEEK_SET);
  827.  
  828.     readNames();
  829.  
  830.     lseek(inf, symbolBase, SEEK_SET);
  831.  
  832.     readSymbols();
  833.  
  834.     // read modules
  835.     if (debugHeader.modulesCount) {
  836.         modules = new DebugModule[debugHeader.modulesCount];
  837.         if (!modules) {
  838.             loadError("cannot allocate modules\n");
  839.             return DPMI_ERR;
  840.         }
  841.  
  842.         bytes = debugHeader.modulesCount*sizeof(DebugModule);
  843.         sz=read(inf, modules, bytes);
  844.         if (sz!=bytes) {
  845.             loadError("cannot read modules\n");
  846.             return DPMI_ERR;
  847.         }
  848.  
  849.         int i;
  850.         for (i=0;i<debugHeader.modulesCount;i++) {
  851.             DebugModule *p = modules+i;
  852.             dprintf("Module %3d: %-20s\n",
  853.                 i, symbolName(p->moduleName));
  854.         }
  855.     }
  856.  
  857.     // read source files
  858.     if (debugHeader.sourceCount) {
  859.         sourceFiles = new DebugSourceFile[debugHeader.sourceCount];
  860.         if (!sourceFiles) {
  861.             loadError("cannot allocate sourceFiles\n");
  862.             return DPMI_ERR;
  863.         }
  864.  
  865.         bytes = debugHeader.sourceCount*sizeof(DebugSourceFile);
  866.         sz=read(inf, sourceFiles, bytes);
  867.         if (sz!=bytes) {
  868.             loadError("cannot read sourceFiles\n");
  869.             return DPMI_ERR;
  870.         }
  871.  
  872.         int i;
  873.         for (i=0;i<debugHeader.sourceCount;i++) {
  874.             DebugSourceFile *p = sourceFiles+i;
  875.             dprintf("SourceFile %3d: %-20s\n",
  876.                 i+1, symbolName(p->sourceFileName));
  877.         }
  878.     }
  879.  
  880.     readLineNumbers();
  881.  
  882.     // read scope records
  883.     if (debugHeader.scopesCount) {
  884.         scopeRecords = new DebugScope[debugHeader.scopesCount];
  885.         if (!scopeRecords) {
  886.             loadError("cannot allocate scope records\n");
  887.             return DPMI_ERR;
  888.         }
  889.  
  890.         bytes = debugHeader.scopesCount*sizeof(DebugScope);
  891.         sz=read(inf, scopeRecords, bytes);
  892.         if (sz!=bytes) {
  893.             loadError("cannot read scope records\n");
  894.             return DPMI_ERR;
  895.         }
  896.     }
  897.  
  898.     // read segments
  899.     if (debugHeader.segmentCount) {
  900.         segments = new DebugSegment[debugHeader.segmentCount];
  901.         if (!segments) {
  902.             loadError("cannot allocate segment records\n");
  903.             return DPMI_ERR;
  904.         }
  905.  
  906.         bytes = debugHeader.segmentCount*sizeof(DebugSegment);
  907.         sz=read(inf, segments, bytes);
  908.         if (sz!=bytes) {
  909.             loadError("cannot read segment records\n");
  910.             return DPMI_ERR;
  911.         }
  912.  
  913.         int i;
  914.         for (i=0;i<debugHeader.segmentCount;i++) {
  915.             DebugSegment *p = segments+i;
  916.             dprintf("Segment %3d: %04x:%04x,%04x %-20s\n",
  917.                 i+1, p->codeSegment, p->codeOffset, p->codeLength,
  918.                 moduleName(p->modIndex) );
  919.         }
  920.     }
  921.  
  922.     // read correlations
  923.     if (debugHeader.correlationCount) {
  924.         correlations = new DebugCorrelation[debugHeader.correlationCount];
  925.         if (!correlations) {
  926.             loadError("cannot allocate correlation records\n");
  927.             return DPMI_ERR;
  928.         }
  929.  
  930.         bytes = debugHeader.correlationCount*sizeof(DebugCorrelation);
  931.         sz=read(inf, correlations, bytes);
  932.         if (sz!=bytes) {
  933.             loadError("cannot read correlation records\n");
  934.             return DPMI_ERR;
  935.         }
  936.  
  937.         int i;
  938.         for (i=0;i<debugHeader.correlationCount;i++) {
  939.             DebugCorrelation *p = correlations+i;
  940.             dprintf("Correlation %3d: seg %3d file %3d lines %4d for %4d\n",
  941.                 i+1, p->segmentIndex, p->fileIndex, p->linesIndex, p->linesCount);
  942.         }
  943.     }
  944.     return DPMI_OK;
  945. }
  946.  
  947. //=====================================================================
  948. //
  949. //  allocateSelectors
  950. //
  951. //  allocates selectors and memory for the executable we are trying to
  952. //  load.
  953. //
  954. //  Note that all segments are set with access rights for a data
  955. //  segment so that we can load and initialize them.
  956. //
  957. //  Also, we create two selectors that point to the first segment,
  958. //  because the FPU code wants to write to the code segment.
  959. //=====================================================================
  960. int allocateSelectors(int nSelectors, SegmentTable *segTable, Selector *selectors)
  961. {
  962.     int i;
  963.     unsigned baseSelector, selectorIncrement;
  964.     int res;
  965.  
  966.     res = Dpmi.allocateLdtDescriptors(2*nSelectors+1,  baseSelector);
  967.     if (res!=0) {
  968.         errprint("Cannot allocate ldt descriptors\n");
  969.         return DPMI_ERR;
  970.     }
  971.  
  972.     res = Dpmi.getSelectorIncrementValue(selectorIncrement);
  973.     if (res!=0) {
  974.         errprint("Cannot get selector increment value\n");
  975.         return DPMI_ERR;
  976.     }
  977.  
  978.     // get to an even selector so we can create a DS alias
  979.     // for the first code segment.
  980.  
  981.     if (baseSelector&selectorIncrement) {
  982.         Dpmi.freeSelector(baseSelector);
  983.         baseSelector += selectorIncrement;
  984.     }
  985.     else {
  986.         Dpmi.freeSelector(baseSelector+(nSelectors+1)*selectorIncrement);
  987.     }
  988.  
  989.     for (i=1;i<=nSelectors;i++) {
  990.         selectors[i] = baseSelector;
  991.         baseSelector += selectorIncrement;
  992.         // double allocate selectors for the first segment
  993.         if (i==1)
  994.             baseSelector += selectorIncrement;
  995.     }
  996.  
  997.     // now allocate and map memory
  998.  
  999.     for (i=1;i<=nSelectors;i++) {
  1000.         unsigned memsize = segTable[i].allocatedSize;
  1001.         Selector selector = selectors[i];
  1002.         dprintf("Creating selector %d %04xh\n", i, selector);
  1003.         long handle, linear;
  1004.         int res = Dpmi.allocateMemory(memsize, linear, handle);
  1005.         dprintf("\tallocate_memory returns: %04xh, linear=%08xh, handle=%08lx\n",
  1006.             res, linear, handle);
  1007.         if (res!=DPMI_OK) return DPMI_ERR;
  1008.  
  1009.         res = Dpmi.lockMemory(linear, memsize);
  1010.         if (res!=DPMI_OK) return DPMI_ERR;
  1011.  
  1012.         do {
  1013.             dprintf("\tset selector base\n");
  1014.             res=Dpmi.setSelectorBase(selector, linear);
  1015.             if (res!=DPMI_OK) return DPMI_ERR;
  1016.             dprintf("\tset selector size\n");
  1017.             res=Dpmi.setSelectorLimit(selector, memsize);
  1018.             if (res!=DPMI_OK) return DPMI_ERR;
  1019.             dprintf("\tset access rights\n");
  1020.             res=Dpmi.setAccessRights(selector, AccessRightsData);
  1021.             if (res!=DPMI_OK) return DPMI_ERR;
  1022.             selector ^= selectorIncrement;
  1023.         } while ((i==1)&&(selector&selectorIncrement)!=0);
  1024.     }
  1025.     return DPMI_OK;
  1026. }
  1027.  
  1028. //=====================================================================
  1029. //
  1030. //  adjustAccessRights
  1031. //
  1032. //  Change the access rights for executable segments to be executable.
  1033. //
  1034. //  This is probably the last thing we do before we're really ready to
  1035. //  run.
  1036. //
  1037. //=====================================================================
  1038. int adjustAccessRights(int nSegs, SegmentTable *st, Selector *selectors)
  1039. {
  1040.  
  1041.     int i;
  1042.     for (i=1;i<=nSegs;i++) {
  1043.         if ((st[i].attributes&7)==0) {
  1044.             dprintf("Segment %d is executable\n", i);
  1045.             int res=Dpmi.setAccessRights(selectors[i], AccessRightsCode);
  1046.             if (res!=DPMI_OK) return DPMI_ERR;
  1047.         }
  1048.     }
  1049.     return DPMI_OK;
  1050. }
  1051.  
  1052. //=====================================================================
  1053. //
  1054. //  read_header
  1055. //
  1056. //  read the header for the executable file
  1057. //
  1058. //=====================================================================
  1059. void read_header(int inf, HEADER *header)
  1060. {
  1061.     int i;
  1062.     char sig[3];
  1063.     i = read(inf,(char *) header, sizeof(HEADER) );
  1064.     if (i<sizeof(HEADER)) {
  1065.         dprintf("cannot read .exe header\n");
  1066.         exit(1);
  1067.     }
  1068.     sig[0] = header->signature[0];
  1069.     sig[1] = header->signature[1];
  1070.     sig[2]=0;
  1071.     dprintf(";signature = %s\n",sig);
  1072.     dprintf(";lastpagebytes = %d\n",header->lastpagebytes);
  1073.     dprintf(";numpages      = %d\n",header->numpages);
  1074.     dprintf(";numreloc      = %d\n",header->numreloc);
  1075.     dprintf(";headersize    = %d\n",header->headersize);
  1076.     dprintf(";minalloc      = %d\n",header->minalloc);
  1077.     dprintf(";maxalloc      = %d\n",header->maxalloc);
  1078.     dprintf(";initialss     = %04x\n",header->initialss);
  1079.     dprintf(";initialsp     = %04x\n",header->initialsp);
  1080.     dprintf(";checksum      = %04x\n",header->checksum);
  1081.     dprintf(";initialip     = %04x\n",header->initialip);
  1082.     dprintf(";initialcs     = %04x\n",header->initialcs);
  1083.     dprintf(";relocoffs     = %04x\n",header->relocoffs);
  1084.     dprintf(";overlaynum    = %04x\n",header->overlaynum);
  1085. }
  1086.  
  1087. //=====================================================================
  1088. //
  1089. //  read_new_header
  1090. //
  1091. //  read the new executable header.
  1092. //
  1093. //=====================================================================
  1094. void read_new_header(int inf, NEHEADER *header)
  1095. {
  1096.     int i;
  1097.     char sig[3];
  1098.     i = read(inf,(char *) header, sizeof(NEHEADER) );
  1099.     if (i<sizeof(NEHEADER)) {
  1100.         dprintf("cannot read new executable header\n");
  1101.         exit(1);
  1102.     }
  1103.     sig[0] = header->signature[0];
  1104.     sig[1] = header->signature[1];
  1105.     sig[2]=0;
  1106.     dprintf(";signature = %s\n",sig);
  1107.     if (sig[0]!='N'||sig[1]!='E') return;
  1108.     dprintf(";linker version %d.%d\n",
  1109.             header->linkMajor, header->linkMinor);
  1110.     dprintf(";entry table at 0x%04x for 0x%04x\n",
  1111.             header->entryOffset, header->entryLength);
  1112.     dprintf(";crc is 0x%08lx\n", header->crc);
  1113.     dprintf(";program flags     are 0x%02x\n", header->programFlags);
  1114.     dprintf(";application flags are 0x%02x\n", header->applicationFlags);
  1115.     dprintf(";data segment index is 0x%04x\n", header->dataSegmentIndex);
  1116.     dprintf(";initialHeapSize    is 0x%04x\n", header->initialHeapSize);
  1117.     dprintf(";initialStackSize   is 0x%04x\n", header->initialStackSize);
  1118.     dprintf(";initialIP          is %04x:%04x\n",
  1119.                 header->initialCS,
  1120.                 header->initialIP);
  1121.     dprintf(";Alignment Shift    is %6d\n", header->fileAlignmentShift);
  1122.     dprintf(";Segment Count      is %6d\n", header->segmentCount);
  1123.     dprintf(";SegmentTableOffset is 0x%04x\n", header->segmentTableOffset);
  1124. }
  1125.  
  1126. //=====================================================================
  1127. //
  1128. //  read_segment_table
  1129. //
  1130. //  read the segment table entries from a new executable
  1131. //
  1132. //=====================================================================
  1133. void RealModuleLoader::read_segment_table(int inf, int nsegs, SegmentTable *tablePtr)
  1134. {
  1135.     int i;
  1136.     char sig[3];
  1137.     int bytes = nsegs*sizeof(SegmentTable);
  1138.     i = read(inf,(char *) (tablePtr+1), bytes);
  1139.     if (i<bytes) {
  1140.         dprintf("cannot read segment table\n");
  1141.         exit(1);
  1142.     }
  1143.     for (i=1;i<=nsegs;i++) {
  1144.         SegmentTable *p = tablePtr + i;
  1145.         dprintf(";Segment[%d] at 0x%08lx, len=0x%04x, attr=0x%04x, alloc=0x%04x %s\n",i,
  1146.             ((long) p->offsetToSegment) << newHeader.fileAlignmentShift,
  1147.             p->length,
  1148.             p->attributes,
  1149.             p->allocatedSize,
  1150.             p->attributes&0x100?"relocations":"");
  1151.     }
  1152. }
  1153.  
  1154.  
  1155. //=====================================================================
  1156. //
  1157. //  readRelocations reads the relocation entries for a segment and
  1158. //  applies them.
  1159. //
  1160. //=====================================================================
  1161. int RealModuleLoader::readRelocations(int segNr, SegmentTable *st, Selector *selectors)
  1162. {
  1163.     //-----------------------------------------------------------------------
  1164.     // The relocation table consists of a word containing the number of
  1165.     // relocation entries followed by the entries themselves.
  1166.     //
  1167.     // Each relocation entry has 4 words.
  1168.     //
  1169.     //              Type of selector
  1170.     //              |   0402 means only highword selector to xx
  1171.     //              |   0002 means only highword selector to xx
  1172.     //                |    0003 means full DWORD selector/offset
  1173.     //                |    0005 means only offset within segment
  1174.     //                |    not sure about other relocation entries
  1175.     //              |
  1176.     //                |    Offset to be repaired
  1177.     //                |    |    Selector Value to insert
  1178.     //                |    |    |      Selector Offset
  1179.     //              |    |    |    |
  1180.     //                v    v      v    v
  1181.     //  Entry  0: 0402 0001 0003 0000
  1182.     //  Entry  1: 0402 005e 0003 02ca
  1183.     //  Entry  2: 0402 00a3 0003 02ca
  1184.     //  Entry  3: 0003 014d 0002 0000
  1185.     //  Entry  4: 0402 181b 0001 1a06
  1186.     //  
  1187.     //-----------------------------------------------------------------------
  1188.     //    dprintf("reading relocation entries for %d\n", segNr);
  1189.     long pos = ((long) st->offsetToSegment) << newHeader.fileAlignmentShift;
  1190.     pos += st->length;
  1191.  
  1192.     lseek(inf, pos, SEEK_SET);
  1193.     WORD nEntries;
  1194.     unsigned bytes = read(inf, (char *)&nEntries, sizeof(WORD));
  1195.     if (bytes!=sizeof(WORD)) {
  1196.         errprint("error reading relocation entries\n");
  1197.         loadErrorCount++;
  1198.         return DPMI_ERR;
  1199.     }
  1200.  
  1201.     // adjust computed end of image so we can get to debug info OK.
  1202.  
  1203.     pos += sizeof(WORD) + nEntries*4*sizeof(WORD);
  1204.     if (pos>endOfImage) endOfImage = pos;
  1205.  
  1206. //    dprintf("there are %d entries\n", nEntries);
  1207.  
  1208.     WORD *relocTable = new WORD[nEntries*4];
  1209.     if (!relocTable) return DPMI_ERR;
  1210.  
  1211.     bytes=read(inf, (char *)(relocTable), 4*sizeof(WORD)*nEntries);
  1212.     if (bytes!=4*sizeof(WORD)*nEntries) {
  1213.         errprint("error reading relocation entries\n");
  1214.         loadErrorCount++;
  1215.         return DPMI_ERR;
  1216.     }
  1217.     int i;
  1218.     WORD *reloc = relocTable;
  1219.     for (i=0;i<nEntries;i++,reloc+=4) {
  1220. //        dprintf("\tRelocation Entry %2d: %04x %04x %04x %04x\n",
  1221. //                i, reloc[0], reloc[1], reloc[2], reloc[3]);
  1222.         unsigned targetType = reloc[0] >> 8;
  1223.         switch (targetType) {
  1224.             case 0:
  1225.             case 4:
  1226.                 switch (reloc[0]&0xff) {    // relocation type
  1227.                     case 0x0002:    // 16 bit selector
  1228.                         {
  1229.                         WORD _far *w;
  1230.                         FP_SEG(w) = selectors[segNr];
  1231.                         FP_OFF(w) = reloc[1];
  1232.                         *w = selectors[reloc[2]];
  1233.                         }
  1234.                         break;
  1235.                     case 0x0003:
  1236.                         {
  1237.                         WORD _far *w;
  1238.                         FP_SEG(w) = selectors[segNr];
  1239.                         FP_OFF(w) = reloc[1];
  1240.                         *w++ = reloc[3];
  1241.                         *w = selectors[reloc[2]];
  1242.                         }
  1243.                         break;
  1244.                     case 0x0005:
  1245.                         {
  1246.                         WORD _far *w;
  1247.                         FP_SEG(w) = selectors[segNr];
  1248.                         FP_OFF(w) = reloc[1];
  1249.                         *w = reloc[3];
  1250.                         }
  1251.                         break;
  1252.                     default:
  1253.                         dprintf("*\twhen reading relocation entries for %d:\n", segNr);
  1254.                         dprintf("*\tBad Relocation Entry %2d: %04x %04x %04x %04x\n",
  1255.                             i, reloc[0], reloc[1], reloc[2], reloc[3]);
  1256.                         loadErrorCount++;
  1257.                         break;
  1258.                 }
  1259.                 break;
  1260.             case 7:
  1261.                 // these appear to be line number table fixups
  1262.                 // I only get them when I compile with Line Number debug info
  1263.                 break;
  1264.  
  1265.             default:
  1266.                 dprintf("*\twhen reading relocation entries for %d:\n", segNr);
  1267.                 dprintf("*\tBad Relocation Entry %2d: %04x %04x %04x %04x\n",
  1268.                     i, reloc[0], reloc[1], reloc[2], reloc[3]);
  1269.                 loadErrorCount++;
  1270.         }
  1271.     }
  1272.     delete [] relocTable;
  1273.     return DPMI_OK;
  1274. }
  1275.  
  1276. //=====================================================================
  1277. //
  1278. //  readSegmentData reads the segment data (code) from the new
  1279. //  executable and then reads and applies the relocation entries.
  1280. //
  1281. //=====================================================================
  1282. int RealModuleLoader::readSegmentData(int nsegs, SegmentTable *tablePtr, Selector *selectors)
  1283. {
  1284.     int i;
  1285.     for (i=1;i<=nsegs;i++) {
  1286.         SegmentTable *st = tablePtr+i;
  1287.         char _far *p = 0;
  1288.         FP_SEG(p) = selectors[i];
  1289.         long pos = ((long) st->offsetToSegment) << newHeader.fileAlignmentShift;
  1290.         lseek(inf, pos, SEEK_SET);
  1291.         DWORD bytes = lread(inf, p, DWORD(st->length) );
  1292.         if (bytes!=st->length) return DPMI_ERR;
  1293.         if (pos+bytes>endOfImage)
  1294.             endOfImage = pos+bytes;
  1295.         dprintf("Load Segment %d, pos=%08lx, bytes=%08lx, end=%08lx\n",
  1296.             i, pos, bytes, endOfImage);
  1297.     }
  1298.  
  1299.     for (i=1;i<=nsegs;i++) {
  1300.         SegmentTable *p = tablePtr + i;
  1301.         if (p->attributes&0x100) {
  1302.             readRelocations(i, tablePtr+i, selectors);
  1303.         }
  1304.     }
  1305.     return DPMI_OK;
  1306. }
  1307.  
  1308.  
  1309. //=====================================================================
  1310. //
  1311. //  RealModuleLoader Class Methods
  1312. //
  1313. //=====================================================================
  1314.  
  1315. SegmentTable *RealModuleLoader::allocSegTables(int n)
  1316. {
  1317.     segTable = new SegmentTable[n];
  1318.     return segTable;
  1319. }
  1320.  
  1321. Selector *RealModuleLoader::allocSelectors(int n)
  1322. {
  1323.     selectors = new Selector[n];
  1324.     return selectors;
  1325. }
  1326.  
  1327. void RealModuleLoader::adjustSelectors()
  1328. {
  1329.     dprintf("adjust selectors: segs = %d, segtable = %08lx, selectors=%08lx\n",
  1330.             newHeader.segmentCount, segTable, selectors);
  1331.     adjustAccessRights(newHeader.segmentCount, segTable, selectors);
  1332. }
  1333.  
  1334. void _far *RealModuleLoader::entryPoint()
  1335. {
  1336.     void _far *p;
  1337.     FP_SEG(p) = selectors[newHeader.initialCS];
  1338.     FP_OFF(p) = newHeader.initialIP;
  1339.     dprintf("program entry point is: %04x:%04x\n", FP_SEG(p), FP_OFF(p) );
  1340.     return p;
  1341. }
  1342.  
  1343. int RealModuleLoader::getLogicalSelector(WORD cs, WORD& lcs)
  1344. {
  1345.     WORD i;
  1346.     for (i=1;i<newHeader.segmentCount;i++)
  1347.         if (selectors[i]==cs) {
  1348.             lcs = i;
  1349.             return 1;
  1350.         }
  1351.     return 0;
  1352. }
  1353.  
  1354. char *RealModuleLoader::describeFaultPc(WORD& nearCs, WORD cs, WORD ip)
  1355. {
  1356.     static char buf[20];
  1357.     WORD lcs;
  1358.     if (cs==_CS) {
  1359.         sprintf(buf, "dpmirun %04x:%04x", cs, ip);
  1360.         return buf;
  1361.     }
  1362.     else if (getLogicalSelector(cs, lcs)) 
  1363.         nearCs = cs;
  1364.     else { // probably a near call
  1365.         if (!getLogicalSelector(nearCs, lcs)) {
  1366.             sprintf(buf, "physical %04x:%04x", cs, ip);
  1367.             return buf;
  1368.         }
  1369.     }
  1370.     return debugInfo->describeFaultPc(lcs,ip);
  1371. }
  1372.  
  1373. void far *RealModuleLoader::getStack(unsigned stkSize)
  1374. {
  1375.     Selector stkSelector;
  1376.     if (Dpmi.getMappedMemory(stkSize, stkSelector, AccessRightsData)!=DPMI_OK)
  1377.         return NULL;
  1378.     return MK_FP(stkSelector, 0);
  1379. }
  1380.  
  1381. //=====================================================================
  1382. //
  1383. //  loadExecutable
  1384. //
  1385. //  This routine loads the executable and returns a ModuleLoader
  1386. //  object to deal with the results.
  1387. //
  1388. //=====================================================================
  1389. void RealModuleLoader::loadExecutable(char *exeName)
  1390. {
  1391.     strcpy(fname,exeName);
  1392.     inf = open(fname, O_RDONLY|O_BINARY);
  1393.     if (inf<0) {
  1394.         errprint("input %s not found\n",fname);
  1395.         Dpmi.dosExit(1);
  1396.     }
  1397.  
  1398.     read_header(inf,&header);
  1399.     headeroffset = ((long) header.headersize)*16;
  1400.     lastbyte = ((long) header.numpages)*512 + header.lastpagebytes;
  1401.  
  1402.     headeroffset = ((long) header.morejunk[14]);
  1403.  
  1404.     lseek(inf, headeroffset, SEEK_SET);
  1405.  
  1406.     read_new_header(inf, &newHeader);
  1407.  
  1408.     lseek(inf, headeroffset+newHeader.segmentTableOffset, SEEK_SET);
  1409.  
  1410.     segTable = allocSegTables( newHeader.segmentCount+1 );
  1411.     if (!segTable) {
  1412.         errprint("cannot allocate segTable\n");
  1413.         Dpmi.dosExit(1);
  1414.     }
  1415.  
  1416.     selectors = allocSelectors(newHeader.segmentCount+1);
  1417.     if (!selectors) {
  1418.         errprint("cannot allocate selectors array\n");
  1419.         Dpmi.dosExit(1);
  1420.     }
  1421.  
  1422.     read_segment_table(inf, newHeader.segmentCount, segTable);
  1423.  
  1424.     if (allocateSelectors(newHeader.segmentCount, segTable, selectors)!=DPMI_OK) {
  1425.         errprint("cannot allocate selectors\n");
  1426.         Dpmi.dosExit(1);
  1427.     }
  1428.     if (readSegmentData(newHeader.segmentCount, segTable, selectors)!=0) {
  1429.         errprint("cannot read executable data\n");
  1430.     }
  1431.  
  1432.     debugInfo = new DebugInfo(this);
  1433.     debugInfo->readDebugInfo();
  1434.  
  1435.     close(inf);
  1436.  
  1437.     dprintf("executable all loaded...\n");
  1438. }
  1439.  
  1440. //=====================================================================
  1441. //
  1442. //  newModuleLoader
  1443. //
  1444. //  return a new RealModuleLoader as a real instance of the
  1445. //  abstract class ModuleLoader.
  1446. //
  1447. //=====================================================================
  1448. ModuleLoader *newModuleLoader()
  1449. {
  1450.     return new RealModuleLoader;
  1451. }
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.